﻿using CSRedis;
using Manon.Repository.Extensions;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;

namespace Manon.Repository
{
    /// <summary>
    ///在 <see cref="IServiceCollection"/>中安装工作单元依赖注入的扩展方法
    /// </summary>
    public static class UnitOfWorkServiceExtensions
    {
        /// <summary>
        /// 在<see cref ="IServiceCollection"/>中注册给定上下文作为服务的工作单元。
        /// 同时注册了dbcontext
        /// </summary>
        /// <typeparam name="TContext"></typeparam>
        /// <param name="services"></param>
        /// <remarks>此方法仅支持一个db上下文，如果多次调用，将抛出异常。</remarks>
        /// <returns></returns>
        public static IServiceCollection AddUnitOfWorkService<TContext>(this IServiceCollection services, System.Action<DbContextOptionsBuilder> action) where TContext : CommonDbContext
        { 
            EntityPropertiesCache.GetEntityPropertyTypeCache();
            services.AddHttpContextAccessor();
            //注册dbcontext
            services.AddDbContext<TContext>(action, ServiceLifetime.Scoped);
            //注册工作单元 
            services.AddScoped<IUnitOfWork, UnitOfWork>();
            services.AddScoped<ICommonDbContext, TContext>();
            services.AddScoped(typeof(IRepository<>), typeof(Repository<>));
            services.AddScoped<IReposUser, ReposUser>();
            return services;
        }


        /// <summary>
        /// 在<see cref ="IServiceCollection"/>中注册给定上下文作为服务的工作单元。
        /// 同时注册了dbcontext
        /// </summary>
        /// <typeparam name="TContext"></typeparam>
        /// <param name="services"></param>
        /// <remarks>此方法仅支持一个db上下文，如果多次调用，将抛出异常。</remarks>
        /// <returns></returns>
        public static IServiceCollection AddUnitOfWorkServiceWithRedis<TContext>(this IServiceCollection services, System.Action<DbOptions> action) where TContext : CommonDbContext
        {
            DbOptions dbOptions = new DbOptions();
            action(dbOptions);

            if (string.IsNullOrEmpty(dbOptions.RedisConnectionString))
                throw new Exception("分配雪花算法workerid,用到了RedisConnectionString. RedisConnectionString不能为空!");

            RedisHelper.Initialization(new CSRedisClient(dbOptions.RedisConnectionString));
            string key = $"{dbOptions.ProjectName}_workerid";
            int workerId = RedisHelper.Get<int>(key);
            RedisHelper.Set(key, workerId++);
            SnowFlake.machineId = workerId;
            var serverVersion = ServerVersion.Parse(dbOptions.Version);
            EntityPropertiesCache.GetEntityPropertyTypeCache();
            services.AddHttpContextAccessor();
            //注册dbcontext
            services.AddDbContext<TContext>(options =>
            {
                options.UseMySql(dbOptions.ConnectionString, serverVersion);
            }, ServiceLifetime.Scoped);
            //注册工作单元 
            services.AddScoped<IUnitOfWork, UnitOfWork>();
            services.AddScoped<ICommonDbContext, TContext>();
            services.AddScoped(typeof(IRepository<>), typeof(Repository<>));
            services.AddScoped<IReposUser, ReposUser>();
            return services;
        }
    }
}
